#include <iostream>
#include <string>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <cerrno>
#include <cstring>

#include "err.hpp"

namespace my_tcpc
{
    // const std::string defaultip = "8.134.110.23";
    // const uint16_t defaultport = 8088;
    class Client
    {
    public:
        Client(const std::string &ip, const uint16_t &port)
            : _sock(-1), _ip(ip), _port(port)
        {}

        void InitClient()
        {
            // 建立套接字
            _sock = socket(AF_INET, SOCK_STREAM, 0);
            if (_sock == -1)
            {
                std::cerr << "create socket error! code: " << errno << "string error:" << strerror(errno) << std::endl;
                exit(SOCK_ERR);
            }

            // 客户端不需要绑定 在第一次连接时自动绑定

            // 开始连接
            struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            // local.sin_addr.s_addr = inet_ntoa(_ip.c_str());
            inet_aton(_ip.c_str(), &(local.sin_addr));

            //v4版先连接再发信息 每次发送都连接
            int count = 5; // 允许连接五次 五次失败则连接失败
            while (connect(_sock, (struct sockaddr *)(&local), sizeof(local)) != 0)
            {
                if (count)
                {
                    --count;
                    std::cout << "正在尝试重新连接...,还剩:" << count+1 << "次!" << std::endl;
                    sleep(1);
                }
                else
                {
                    std::cerr << "向ip:" << _ip << " 端口:" << _port << "的主机连接失败!" << std::endl;
                    exit(CONNECT_ERR);
                }
            }
        }

        void Start()
        {
            while (true)
            {
                std::string Line;
                std::cout << "请输入消息>";
                std::getline(std::cin, Line);

                write(_sock, Line.c_str(), Line.size());

                char buf[2048] = {0};
                ssize_t n = read(_sock, buf, sizeof(buf) - 1);
                if (n > 0)
                {
                    buf[n] = '\0';
                    std::cout << "server> " << buf << std::endl;
                    continue;
                }
                else if (n == 0)
                {
                    std::cout << "server quit!" << std::endl;
                    break;
                }
                else
                {
                    std::cerr << "read from server error!" << std::endl;
                    break;
                }
            }
            close(_sock); // 关闭套接字文件描述符
        }

    private:
        int _sock;
        std::string _ip;
        uint16_t _port;
    };
};

